#ifndef __CHECK_IMG_H__
#define __CHECK_IMG_H__

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

typedef unsigned long long u64;
typedef unsigned int u32;
typedef unsigned short int u16;
typedef unsigned char u8;

#define __le64 u64
#define __le32 u32
#define __le16 u16

#define __be64 u64
#define __be32 u32
#define __be16 u16

#define __u64 u64
#define __u32 u32
#define __u16 u16
#define __u8 u8

#define EXT4_SUPER_MAGIC 0xEF53

struct ext4_super_block {
  __le32 s_inodes_count;
 __le32 s_blocks_count_lo;
 __le32 s_r_blocks_count_lo;
 __le32 s_free_blocks_count_lo;
  __le32 s_free_inodes_count;
 __le32 s_first_data_block;
 __le32 s_log_block_size;
 __le32 s_obso_log_frag_size;
  __le32 s_blocks_per_group;
 __le32 s_obso_frags_per_group;
 __le32 s_inodes_per_group;
 __le32 s_mtime;
  __le32 s_wtime;
 __le16 s_mnt_count;
 __le16 s_max_mnt_count;
 __le16 s_magic;
 __le16 s_state;
 __le16 s_errors;
 __le16 s_minor_rev_level;
  __le32 s_lastcheck;
 __le32 s_checkinterval;
 __le32 s_creator_os;
 __le32 s_rev_level;
  __le16 s_def_resuid;
 __le16 s_def_resgid;

 __le32 s_first_ino;
 __le16 s_inode_size;
 __le16 s_block_group_nr;
 __le32 s_feature_compat;
  __le32 s_feature_incompat;
 __le32 s_feature_ro_compat;
  __u8 s_uuid[16];
  char s_volume_name[16];
  char s_last_mounted[64];
  __le32 s_algorithm_usage_bitmap;

 __u8 s_prealloc_blocks;
 __u8 s_prealloc_dir_blocks;
 __le16 s_reserved_gdt_blocks;

  __u8 s_journal_uuid[16];
  __le32 s_journal_inum;
 __le32 s_journal_dev;
 __le32 s_last_orphan;
 __le32 s_hash_seed[4];
 __u8 s_def_hash_version;
 __u8 s_reserved_char_pad;
 __le16 s_desc_size;
  __le32 s_default_mount_opts;
 __le32 s_first_meta_bg;
 __le32 s_mkfs_time;
 __le32 s_jnl_blocks[17];

  __le32 s_blocks_count_hi;
 __le32 s_r_blocks_count_hi;
 __le32 s_free_blocks_count_hi;
 __le16 s_min_extra_isize;
 __le16 s_want_extra_isize;
 __le32 s_flags;
 __le16 s_raid_stride;
 __le16 s_mmp_interval;
 __le64 s_mmp_block;
 __le32 s_raid_stripe_width;
 __u8 s_log_groups_per_flex;
 __u8 s_reserved_char_pad2;
 __le16 s_reserved_pad;
 __le64 s_kbytes_written;
 __u32 s_reserved[160];
};


typedef struct sparse_header {
  __le32	magic;		/* 0xed26ff3a */
  __le16	major_version;	/* (0x1) - reject images with higher major versions */
  __le16	minor_version;	/* (0x0) - allow images with higer minor versions */
  __le16	file_hdr_sz;	/* 28 bytes for first revision of the file format */
  __le16	chunk_hdr_sz;	/* 12 bytes for first revision of the file format */
  __le32	blk_sz;		/* block size in bytes, must be a multiple of 4 (4096) */
  __le32	total_blks;	/* total blocks in the non-sparse output image */
  __le32	total_chunks;	/* total chunks in the sparse input image */
  __le32	image_checksum; /* CRC32 checksum of the original data, counting "don't care" */
				/* as 0. Standard 802.3 polynomial, use a Public Domain */
				/* table implementation */
} sparse_header_t;

#define SPARSE_HEADER_MAGIC	0xed26ff3a

#define SPARSE_HEADER_LEN       (sizeof(sparse_header_t))

#define CHUNK_TYPE_RAW		0xCAC1
#define CHUNK_TYPE_FILL		0xCAC2
#define CHUNK_TYPE_DONT_CARE	0xCAC3
#define CHUNK_TYPE_CRC32    0xCAC4

#define COOLPAD_MAGIC 0x55790000

typedef struct chunk_header {
  __le16	chunk_type;	/* 0xCAC1 -> raw; 0xCAC2 -> fill; 0xCAC3 -> don't care */
  __le16	reserved1;
  __le32	chunk_sz;	/* in blocks in output image */
  __le32	total_sz;	/* in bytes of chunk input file including chunk header and data */
} chunk_header_t;

#define CHUNK_HEADER_LEN (sizeof(chunk_header_t))

#define CHUNK_SIZE_1024_32	1024
#define SPARE_SIZE_1024_32	32
#define CHUNK_SIZE_2048_64	2048
#define SPARE_SIZE_2048_64	64
#define CHUNK_SIZE_2050_62	2050
#define SPARE_SIZE_2050_62	62
#define CHUNK_SIZE_4096_128	4096
#define SPARE_SIZE_4096_128	128
#define CHUNK_SIZE_4096_160	4096
#define SPARE_SIZE_4096_160	160
#define DATA_SIZE_4096_160	4096

#define MIN_CHUNK_SIZE		CHUNK_SIZE_1024_32
#define MIN_SPARE_SIZE		SPARE_SIZE_1024_32
#define DEFAULT_CHUNK_SIZE	CHUNK_SIZE_2048_64
#define DEFAULT_SPARE_SIZE	SPARE_SIZE_2048_64
#define MAX_CHUNK_SIZE		CHUNK_SIZE_4096_160
#define MAX_SPARE_SIZE		SPARE_SIZE_4096_160

static const int chunk_size_list_count = 5;
static const unsigned chunk_size_list[] = {
								CHUNK_SIZE_1024_32,
								CHUNK_SIZE_2048_64,
								CHUNK_SIZE_2050_62,
								CHUNK_SIZE_4096_128,
								CHUNK_SIZE_4096_160
};
static const unsigned spare_size_list[] = {
								SPARE_SIZE_1024_32,
								SPARE_SIZE_2048_64,
								SPARE_SIZE_2050_62,
								SPARE_SIZE_4096_128,
								SPARE_SIZE_4096_160
};

#define YAFFS_OBJECTID_ROOT 1

#define YAFFS_MAX_NAME_LENGTH		255
#define YAFFS_MAX_ALIAS_LENGTH		159

/* -------------------------- Object structure -------------------------------*/
/* This is the object structure as stored on NAND */

typedef struct yaffs_obj_hdr{
    enum yaffs_obj_type type;

    /* Apply to everything  */
    int parent_obj_id;
	__u16 sum_no_longer_used;        /* checksum of name. No longer used */
	char name[YAFFS_MAX_NAME_LENGTH + 1];

	/* The following apply to directories, files, symlinks - not hard links */
	__u32 yst_mode;         /* protection */

    __u32 yst_uid;
    __u32 yst_gid;
    __u32 yst_atime;
    __u32 yst_mtime;
    __u32 yst_ctime;

    /* File size  applies to files only */
    //int file_size_low;
	int file_size;

    /* Equivalent object id applies to hard links only. */
    int equiv_id;

    /* Alias is for symlinks only. */
    char alias[YAFFS_MAX_ALIAS_LENGTH + 1];

    __u32 yst_rdev;     /* device stuff for block and char devices (major/min) */

    __u32 win_ctime[2];
    __u32 win_atime[2];
    __u32 win_mtime[2];

    __u32 inband_shadowed_obj_id;
    __u32 inband_is_shrink;

    //__u32 file_size_high;
	__u32 reserved[2];
    int shadows_obj;  /* This object header shadows the specified object if > 0 */

    /* isShrink applies to object headers written when we shrink the file (ie resize) */
    __u32 is_shrink;

} yaffs_ObjectHeader;

typedef struct yaffs_packed_tags2_tags_only{
    unsigned seq_number;
    unsigned obj_id;
    unsigned chunk_id;
    unsigned n_bytes;
} yaffs_PackedTags2TagsPart;

typedef struct yaffs_ecc_other{
    unsigned char col_parity;
    unsigned line_parity;
    unsigned line_parity_prime; 
} yaffs_ECCOther;

typedef struct yaffs_packed_tags2{
	struct yaffs_packed_tags2_tags_only t;
	struct yaffs_ecc_other ecc;
} yaffs_PackedTags2;

typedef enum yaffs_ecc_result{
    YAFFS_ECC_RESULT_UNKNOWN,
    YAFFS_ECC_RESULT_NO_ERROR,
    YAFFS_ECC_RESULT_FIXED,
    YAFFS_ECC_RESULT_UNFIXED
} yaffs_ECCResult;

typedef enum yaffs_obj_type{
    YAFFS_OBJECT_TYPE_UNKNOWN,
    YAFFS_OBJECT_TYPE_FILE,
    YAFFS_OBJECT_TYPE_SYMLINK,
    YAFFS_OBJECT_TYPE_DIRECTORY,
    YAFFS_OBJECT_TYPE_HARDLINK,
    YAFFS_OBJECT_TYPE_SPECIAL
} yaffs_ObjectType;

#define hweight8(x) yaffs_hweight8(x)
#define hweight32(x) yaffs_hweight32(x)

enum yaffs_ecc_result yaffs_check_ecc(struct yaffs_packed_tags2 *pt);
int endWith(const char *str, const char *end);

#define UBI_EC_HDR_MAGIC  0x23494255

#endif
